﻿/*-----------------------------------------------
// File: ModelCore.cs
// Description: Model的相关配置，设置材质的接口，挂载信息
// Author: Kuangyi Shaobing	492057342@qq.com
-----------------------------------------------*/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public enum BodyType
{
    BODY = 0, //身体
    FACE = 1, //脸
}

public delegate void WeaponLoadCompleteNotify();

[RequireComponent(typeof(LegacyAnimation))]
public class ModelRenderKit : MonoBehaviour
{
    public SkinnedMeshRenderer skinnedMeshRenderer;

    public Animation subAnimation;

    //简单的影子,如果不支持Camera RenderTarget
    public Transform shadow;
    public GameObject shadowCircle;

    //武器锚点
    public Transform wuqil;
    public Transform wuqir;

    //武器左右
    public GameObject leftWeapon;
    public GameObject rightWeapon;

    public List<Texture> faceTextures;

    public Texture defaultFaceTexture
    {
        get
        {
            if (_defaultFaceTexture == null)
            {
                foreach (var t in faceTextures)
                {
                    if (t.name.EndsWith("face_n"))
                    {
                        _defaultFaceTexture = t;
                        break;
                    }
                }
            }
            return _defaultFaceTexture;
        }
    }
    Texture _defaultFaceTexture = null;

    public void EnterBattle()
    {
        if (GetComponent<LegacyAnimation>() != null && GetComponent<LegacyAnimation>().anim != null)
        {
            GetComponent<LegacyAnimation>().anim.cullingType = AnimationCullingType.AlwaysAnimate;
        }
        if (subAnimation != null)
        {
            subAnimation.cullingType = AnimationCullingType.AlwaysAnimate;
        }
    }

    public void LeaveBattle()
    {
        if (GetComponent<LegacyAnimation>() != null && GetComponent<LegacyAnimation>().anim != null)
        {
            GetComponent<LegacyAnimation>().anim.cullingType = AnimationCullingType.BasedOnRenderers;
        }
        if (subAnimation != null)
        {
            subAnimation.cullingType = AnimationCullingType.BasedOnRenderers;
        }
    }

    public Texture GetFaceTexture()
    {
        foreach (var mat in skinnedMeshRenderer.materials)
        {
            if (mat.name.Contains("face"))
            {
                return mat.mainTexture;
            }
        }
        return null;
    }

    public void SetDefaultFace()
    {
        if (defaultFaceTexture != null)
        {
            SetFace(defaultFaceTexture);
        }
    }

    public void SetFace(string faceName)
    {
        foreach (var tex in faceTextures)
        {
            if (tex.name == faceName)
            {
                SetFace(tex);
                return;
            }
        }
    }

    public void SetFace(Texture faceTexture)
    {
        if (faceTexture != null)
        {
            foreach (var mat in skinnedMeshRenderer.materials) {
                if (mat.name.Contains("face")) {
                    mat.SetTexture("_MainTex", faceTexture);
                    break;
                }
            }
        }
    }

    public void PlayAnimation(string str, WrapMode mode, bool rewind = false, float speed = 1f)
    {
        if (leftWeapon != null)
        {
            var anims = leftWeapon.GetComponentsInChildren<Animation>();
            foreach (var anim in anims)
            {
                if (anim.GetClip(str) != null)
                {
                    anim[str].wrapMode = mode;
                    anim[str].speed = speed;
                    if (anim.IsPlaying(str) && rewind)
                        anim.Rewind(str);
                    anim.Play(str);
                }
            }
        }
        if (rightWeapon != null)
        {
            var anims = rightWeapon.GetComponentsInChildren<Animation>();
            foreach (var anim in anims)
            {
                if (anim.GetClip(str) != null)
                {
                    anim[str].wrapMode = mode;
                    anim[str].speed = speed;
                    if (anim.IsPlaying(str) && rewind)
                        anim.Rewind(str);
                    anim.Play(str);
                }
            }
        }
    }

    public void AddBattleAni(AnimClipsAsset battleAnis)
    {
        if(battleAnis == null)
        {
            return;
        }
        Animation anim = GetComponent<LegacyAnimation>().anim;
        for(int i = 0; i < battleAnis.clips.Count;++i)
        {
            if (battleAnis.clips[i] == null)
                continue;
            if(anim.GetClip(battleAnis.clips[i].name) != null)
            {
                break;
            }
            anim.AddClip(battleAnis.clips[i], battleAnis.clips[i].name);
        }
    }

    public void RemoveBattleAni()
    {
        Animation anim = GetComponent<LegacyAnimation>().anim;
        for (int i = 0; i < aniNameFight.Length;++i)
        {
            anim.RemoveClip(aniNameFight[i]);
        }
    }
    #region 生活动画
    
    public void AddLifeAni(AnimationClip clip)
    {
        var anim = GetComponent<LegacyAnimation>().anim;
        if(anim.GetClip(clip.name)==null)
        {
            anim.AddClip(clip,clip.name);
        }
    }

    public void RemoveLifeAni(string aniName)
    {
        var anim = GetComponent<LegacyAnimation>().anim;
        if(anim.GetClip(aniName) !=null)
        {
            anim.RemoveClip(aniName);
        }
    }
    #endregion

    int weaponLoadTask = 0;

    public IEnumerator LoadWeaponsDirectly(string leftWeapon, string rightWeapon) {
        UnloadWeapons();
        weaponLoadTask = 0;
        if (!string.IsNullOrEmpty(leftWeapon))
        {
            _LoadWeapon(leftWeapon, true);
            weaponLoadTask++;
        }
        if (!string.IsNullOrEmpty(rightWeapon))
        {
            _LoadWeapon(rightWeapon, false);
            weaponLoadTask++;
        }
        while (weaponLoadTask > 0)
        {
            yield return null;
        }
    }

    public IEnumerator LoadDefaultWeapons(string heroId)
    {
        yield return StartCoroutine(LoadWeapons(heroId, ""));
    }

    #region 生活工具

    /*GameObject fishingRod;
    GameObject mineHoe;
    GameObject fish;

    /*
    public void ShowFishingRod(bool show)
    {

        if (fishingRod==null)
        {
            LoadLifeUtil(show, false);
        }
        if (fishingRod != null)
            fishingRod.SetActive(show);
        if(show)
        {
            ShowFish();
        }
    }
    

    public void ShowMineHoe(bool show)
    {

        if(mineHoe==null)
        {
            LoadLifeUtil(false, show);
        }
        if (mineHoe != null)
            mineHoe.SetActive(show);
        
    }
    

    void ShowFish()
    {
        if (fish != null && gameObject.activeSelf)
        {
            StartCoroutine(_ShowFish());
        }
    }

   

    /*
    public void LoadLifeUtil(bool showFish=false,bool showMine=false)
    {
        var tran = FindBindTransform(transform, "Bip001 R Hand");
        if (fishingRod == null)
        {
            var fishingRodName = Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.FishingRod;
            AssetLoad.AssetBundleManager.Instance.StartCoroutine(
               ResourceLoader.GetInstance().weaponLoader.LoadWeapon(fishingRodName, (asset) =>
               {
                   fishingRod = asset as GameObject;
                   if (fishingRod != null)
                   {
                       fishingRod.transform.SetParent(tran);
                       fishingRod.transform.localPosition = new Vector3(-0.05f,0.025f,-0.224f);
                       fishingRod.transform.localScale = Vector3.one;
                       fishingRod.transform.localRotation = Quaternion.Euler(new Vector3(-2.173f,-7.8f,-99f + 180f));
                       fishingRod.SetActive(showFish);
                   }

               }));

        }

        if (mineHoe == null)
        {
            var mineHoeName = Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.MiningHoe;
            AssetLoad.AssetBundleManager.Instance.StartCoroutine(
               ResourceLoader.GetInstance().weaponLoader.LoadWeapon(mineHoeName, (asset) =>
               {
                   mineHoe = asset as GameObject;
                   if (mineHoe != null)
                   {
                       mineHoe.transform.SetParent(tran);
                       mineHoe.transform.localPosition = new Vector3(-0.05f, 0.025f, -0.224f);
                       mineHoe.transform.localScale = Vector3.one;
                       mineHoe.transform.localRotation = Quaternion.Euler(new Vector3(-2.173f, -7.8f, -99f + 180f));

                       mineHoe.SetActive(showMine);
                   }

               }));
        }

        if(fish == null)
        {
            var fishName = Dict.DictDataManager.Instance.tableGameConfigureDao.currentData.FishModel;
            AssetLoad.AssetBundleManager.Instance.StartCoroutine(
               ResourceLoader.GetInstance().weaponLoader.LoadWeapon(fishName, (asset) =>
               {
                   fish = asset as GameObject;
                   if (fish != null)
                   {
                       fish.transform.SetParent(tran);
                       fish.transform.localPosition = new Vector3(-0.05f, 0.025f, -0.224f);
                       fish.transform.localScale = Vector3.one;
                       fish.transform.localRotation = Quaternion.Euler(new Vector3(-2.173f, -7.8f, -99f + 180f));

                       fish.SetActive(false);
                   }

               }));
        }
    }

    public void UnloadLifeUtil()
    {
        if (fishingRod != null)
            GameObject.Destroy(fishingRod);
        if (mineHoe != null)
            GameObject.Destroy(mineHoe);
    }

    */
    #endregion
    public IEnumerator LoadWeapons(string heroId, string equipId)
    {
        //System.DateTime dt = System.DateTime.Now;
        UnloadWeapons();
        weaponLoadTask = 0;
        var dh = Dict.Blo.DictHeroBlo.GetTableHero(heroId);
        bool isMonster = dh.heroClass == (int)HeroClass.Monster;
        
        if (!isMonster)
        {
            var dw = Dict.Blo.DictWeaponBlo.GetTableWeaponResByHeroIdAndEquipId(heroId, equipId);
            if (dw != null)
            {
                if (!string.IsNullOrEmpty(dw.modelRes0))
                {
                    _LoadWeapon(dw.modelRes0, true);
                    weaponLoadTask++;
                }
                if (!string.IsNullOrEmpty(dw.modelRes1))
                {
                    _LoadWeapon(dw.modelRes1, false);
                    weaponLoadTask++;
                }
                while (weaponLoadTask > 0)
                {
                    yield return null;
                }
            }
            else {
                yield break;
            }
        }
        else
        {
            var dw = Dict.Blo.DictWeaponBlo.GetTableMonsterWeaponResByHeroId(heroId);
            if (dw != null)
            {
                if (!string.IsNullOrEmpty(dw.modelRes0))
                {
                    _LoadWeapon(dw.modelRes0, true);
                    weaponLoadTask++;
                }
                if (!string.IsNullOrEmpty(dw.modelRes1))
                {
                    _LoadWeapon(dw.modelRes1, false);
                    weaponLoadTask++;
                }
                while (weaponLoadTask > 0)
                {
                    yield return null;
                }
            }
            else {
                yield break;
            }
        }
        //Debug.Log("load weapon "+ heroId + " " + equipId + " cost time " + (System.DateTime.Now - dt).TotalMilliseconds);
    }
    public IEnumerator LoadWeapons(string heroId, string equipId,float scale)
    {
        //System.DateTime dt = System.DateTime.Now;
        UnloadWeapons();
        weaponLoadTask = 0;
        var dh = Dict.Blo.DictHeroBlo.GetTableHero(heroId);
        bool isMonster = dh.heroClass == (int)HeroClass.Monster;

        if (!isMonster)
        {
            var dw = Dict.Blo.DictWeaponBlo.GetTableWeaponResByHeroIdAndEquipId(heroId, equipId);
            if (dw != null)
            {
                if (!string.IsNullOrEmpty(dw.modelRes0))
                {
                    _LoadWeapon(dw.modelRes0, true,scale);
                    weaponLoadTask++;
                }
                if (!string.IsNullOrEmpty(dw.modelRes1))
                {
                    _LoadWeapon(dw.modelRes1, false,scale);
                    weaponLoadTask++;
                }
                while (weaponLoadTask > 0)
                {
                    yield return null;
                }
            }
            else
            {
                yield break;
            }
        }
        else
        {
            var dw = Dict.Blo.DictWeaponBlo.GetTableMonsterWeaponResByHeroId(heroId);
            if (dw != null)
            {
                if (!string.IsNullOrEmpty(dw.modelRes0))
                {
                    _LoadWeapon(dw.modelRes0, true);
                    weaponLoadTask++;
                }
                if (!string.IsNullOrEmpty(dw.modelRes1))
                {
                    _LoadWeapon(dw.modelRes1, false);
                    weaponLoadTask++;
                }
                while (weaponLoadTask > 0)
                {
                    yield return null;
                }
            }
            else
            {
                yield break;
            }
        }
        //Debug.Log("load weapon "+ heroId + " " + equipId + " cost time " + (System.DateTime.Now - dt).TotalMilliseconds);
    }
    public void UnloadWeapons()
    {
        if (leftWeapon != null)
        {
            _UnloadWeapon(true);
        }
        if (rightWeapon != null)
        {
            _UnloadWeapon(false);
        }
    }

    void _UnloadWeapon(bool isLeft)
    {
        if (isLeft)
        {
            //ResourceLoader.GetInstance().weaponLoader.UnloadModel(leftWeapon, leftWeapon.name);
            ResourceLoader.GetInstance().weaponLoader.UnloadWeapon(leftWeapon, leftWeapon.name);
            leftWeapon = null;
        }
        else
        {
            //ResourceLoader.GetInstance().weaponLoader.UnloadModel(rightWeapon, rightWeapon.name);
            ResourceLoader.GetInstance().weaponLoader.UnloadWeapon(rightWeapon, rightWeapon.name);
            rightWeapon = null;
        }
    }


    void _LoadWeapon(string resName, bool isLeft)
    {
        Transform wuqi = GetWuqiTransform(isLeft);
        if (wuqi != null) {
            AssetLoad.AssetBundleManager.Instance.StartCoroutine(
            ResourceLoader.GetInstance().weaponLoader.LoadWeapon(resName, (asset) =>
            {
                GameObject weaponObj = asset as GameObject;
                _LoadWeaponComplete(weaponObj, resName, isLeft, wuqi);
                weaponLoadTask--;
            }));
        }
    }


    void _LoadWeaponComplete(GameObject weaponObj, string resName, bool isLeft, Transform wuqi) {
        if (weaponObj != null) {
            weaponObj.name = resName;
            weaponObj.transform.SetParent(wuqi);
            weaponObj.transform.localPosition = Vector3.zero;
            weaponObj.transform.localScale = Vector3.one;
            weaponObj.transform.localEulerAngles = Vector3.zero;
            CommonMethod.ChangeLayer(weaponObj.transform, gameObject.layer);
            if (isLeft)
            {
                if(leftWeapon == null)
                {
                    leftWeapon = weaponObj;
                    weaponObj.SetActive(true);
                }
                else
                {
                    ResourceLoader.GetInstance().weaponLoader.UnloadWeapon(weaponObj, weaponObj.name);
                }
            }
            else
            {
                if (rightWeapon == null)
                {
                    rightWeapon = weaponObj;
                    weaponObj.SetActive(true);
                }
                else
                {
                    ResourceLoader.GetInstance().weaponLoader.UnloadWeapon(weaponObj, weaponObj.name);
                }
            }
        }


    }

    //
    void _LoadWeapon(string resName, bool isLeft,float scale)
    {
        Transform wuqi = GetWuqiTransform(isLeft);
        if (wuqi != null)
        {
            AssetLoad.AssetBundleManager.Instance.StartCoroutine(
            ResourceLoader.GetInstance().weaponLoader.LoadWeapon(resName, (asset) =>
            {
                GameObject weaponObj = asset as GameObject;
                ParticleSystem[] obj = weaponObj.GetComponentsInChildren<ParticleSystem>();
                foreach (var aa in obj)
                {
                    aa.startSize *= scale;
                }
                Transform eff = weaponObj.transform.FindChild("effect");
                if (eff != null)
                {
                    eff.gameObject.SetActive(false);
                }

                _LoadWeaponComplete(weaponObj, resName, isLeft, wuqi,scale);
                weaponLoadTask--;
            }));
        }
    }


    void _LoadWeaponComplete(GameObject weaponObj, string resName, bool isLeft, Transform wuqi,float scale)
    {
        if (weaponObj != null)
        {
            weaponObj.name = resName;
            Transform eff = weaponObj.transform.FindChild("effect");
            if (eff != null)
            {
                eff.gameObject.SetActive(true);
            }
            weaponObj.transform.SetParent(wuqi);
            weaponObj.transform.localPosition = Vector3.zero;
            weaponObj.transform.localScale = Vector3.one;
            weaponObj.transform.localEulerAngles = Vector3.zero;
            if (isLeft)
            {
                if (leftWeapon == null)
                {
                    leftWeapon = weaponObj;
                    weaponObj.SetActive(true);
                }
                else
                {
                    ResourceLoader.GetInstance().weaponLoader.UnloadWeapon(weaponObj, weaponObj.name);
                }
            }
            else
            {
                if (rightWeapon == null)
                {
                    rightWeapon = weaponObj;
                    weaponObj.SetActive(true);
                }
                else
                {
                    ResourceLoader.GetInstance().weaponLoader.UnloadWeapon(weaponObj, weaponObj.name);
                }
            }
        }


    }


    public void SwitchLod(bool isOn)
    {
        //if (isOn)
        //{
        //    for (int i = 0; i < skinnedMeshRenderer.materials.Length; ++i)
        //    {
        //        skinnedMeshRenderer.materials[i].DisableKeyword("LOD_OFF");
        //    }
        //}
        //else
        //{
        //    for (int i = 0; i < skinnedMeshRenderer.materials.Length; ++i)
        //    {
        //        skinnedMeshRenderer.materials[i].EnableKeyword("LOD_OFF");
        //    }
        //}
    }

    internal Transform GetWuqiTransform(bool isLeft)
    {
        Transform wuqi = null;
        if (isLeft)
        {
            wuqi = wuqil;
        }
        else
        {
            wuqi = wuqir;
        }
        if (wuqi == null)
        {
            var obj = FindAnthor(isLeft ? "wuqil" : "wuqir");
            if (obj != null)
            {
                wuqi = obj.transform;
            }
        }
        return wuqi;
    }

    public void UltimateChangeWeapons(string leftRes, string rightRes)
    {
        StartCoroutine(_UltimateChangeWeapons(leftRes, rightRes));
    }

    IEnumerator _UltimateChangeWeapons(string leftRes, string rightRes)
    {
        UnloadWeapons();
        weaponLoadTask = 0;
        if (!string.IsNullOrEmpty(leftRes))
        {
            _LoadWeapon(leftRes, true);
            weaponLoadTask++;
        }
        if (!string.IsNullOrEmpty(rightRes))
        {
            _LoadWeapon(rightRes, false);
            weaponLoadTask++;
        }
        while (weaponLoadTask > 0)
            yield return null;
    }

    public GameObject FindAnthor(string str)
    {
        var childs = transform.GetComponentsInChildren<Transform>();
        foreach (var it in childs)
        {
            if (str == it.name)
            {
                return it.gameObject;
            }
        }
        Transform ant = GetChildByName(transform, str);
        if(ant != null)
        {
            return ant.gameObject;
        }
        Debug.LogError("[DEBUG] can't find anthor:" + str);
        return null;
    }

    private Transform GetChildByName(Transform trans,string name)
    {
        if(trans.name == name)
        {
            return trans;
        }
        foreach(Transform t in trans)
        {
            if(GetChildByName(t,name) != null)
            {
                return t;
            }
        }
        return null;
    }

    public List<Renderer> GetWuqiRenderers()
    {
        List<Renderer> renders = new List<Renderer>();
        if (leftWeapon != null)
        {
            foreach (var render in leftWeapon.GetComponentsInChildren<Renderer>())
            {
                renders.Add(render);
            }
        }
        if (rightWeapon != null)
        {
            foreach (var render in rightWeapon.GetComponentsInChildren<Renderer>())
            {
                renders.Add(render);
            }
        }

        return renders;
    }

    public List<GameObject> GetWeaponEffects()
    {
        List<GameObject> list = new List<GameObject>();

        if(leftWeapon != null)
        {
            var trans =  leftWeapon.GetComponentsInChildren<Transform>();
            foreach(var tran in trans)
            {
                if(tran.gameObject.name == "effect" )
                {
                    list.Add(tran.gameObject);
                }
            }
        }

        if(rightWeapon!=null)
        {
            var trans = rightWeapon.GetComponentsInChildren<Transform>();
            foreach (var tran in trans)
            {
                if (tran.gameObject.name == "effect")
                {
                    list.Add(tran.gameObject);
                }
            }
        }

        return list;
    }
	public void ShowSimpleShadow()
	{
		ShowSimpleShadow (RenderManager.simpleShadowTex);
	}

	public void ShowSimpleShadow(GameObject objTemp)
    {
        if (shadowCircle == null)
        {

            if (shadow == null)
            {
                shadow = gameObject.transform.Find("shadow");
            }

            if (shadow != null)
            {
                if (!shadow.gameObject.activeSelf)
                {
                    shadow.gameObject.SetActive(true);
                }

				if (objTemp != null)
                {
                    //GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Quad);

					var obj = GameObject.Instantiate (objTemp) as GameObject;
                    obj.transform.SetParent(shadow);
                    obj.transform.localScale = Vector3.one * 2f;

                    obj.transform.localRotation = Quaternion.Euler(new Vector3(0f, -180f, -180f));

                    obj.transform.localPosition = new Vector3(0f, 0f, 0.01f); ;
                    obj.SetActive(true);

                    //obj.GetComponent<MeshCollider>().enabled = false;
					//Destroy (obj.GetComponent<MeshCollider>());
					//Material mat = new Material (Shader.Find("Unlit/Transparent"));
					//mat.mainTexture = tex;
					//obj.GetComponent<MeshRenderer>().material = mat;
					//obj.GetComponent<MeshRenderer>().material.SetTexture("_MainTex", tex);
                    shadowCircle = obj;
                }

            }
        }
        else
        {
            shadowCircle.SetActive(true);
        }
    }

    public void HideSimpleShadow()
    {
        if (shadowCircle != null)
        {
            shadowCircle.SetActive(false);
        }
    }

    void Update()
    {
        if (Room.RoomManager.curSceneType == SceneType.BATTLE)
        {
			if (RenderManager.GetInstance ().RenderTargetShadow) {
				HideSimpleShadow ();
			} 
			else 
			{
				ShowSimpleShadow ();
			}
        }
    }

    public void SetModelScale(float scale)
    {
        this.transform.localScale = Vector3.one * scale; 
    }

    public void SetWeaponEffectLayer(string layerName)
    {
        foreach(var render in GetWeaponEffects())
        {
            render.gameObject.layer = LayerMask.NameToLayer(layerName);
            foreach(var tran in render.gameObject.GetComponentsInChildren<Transform>())
            {
                tran.gameObject.layer = LayerMask.NameToLayer(layerName);
            }
        }
    }

    public Transform GetBindTransform(string bindName) {
        Transform res = null;
        res = FindBindTransform(transform, bindName);
        if (res != null)
        {
            if (bindName == "root")
            {
                return res.parent;
            }
            else {
                return res;
            }
        }
        return null;
    }
    Transform FindBindTransform(Transform trans, string bindName)
    {
        if (trans.name == bindName)
        {
            return trans;
        }
        foreach (Transform t in trans)
        {
            var _t = FindBindTransform(t, bindName);
            if (_t != null)
            {
                return _t;
            }
        }
        return null;
    }

    public Transform GetTransform(string boneName)
    {
        return FindBindTransform(transform, boneName);
    }

    private string[] aniNameFight = { "attack01", "attack02", "attack03", "dizzy", "falla","fallb","fallc",
        "floata","hit","jumpb","rush"};
    


#if UNITY_EDITOR
    //public void OnDisable()
    //{
    //    Debug.Log(name + " be disabled ");
    //}
#endif
}
